from rest_framework import response
from django.conf import settings
from django.http.response import HttpResponse
import json
import random
import string
import base64
import socket
import datetime
import hashlib
import calendar


class Formatting(object):

    def __init__(self, string):
        # assert type(string) == str, ("'%s' not's string type!" % string)
        self.string = string

    def __format__(self, format_spec='en'):
        """
        转换字符串中的符号，调用方法为'类对象.__format__(format_spec)'
        :param format_spec:
                ch: 格式规范为中文，把符号都转换成中文的
                en: 格式规范为英文，把符号都转换为英文的
                默认为转换英文格式
        :return: 转换后的字符串
        """
        # if not format_spec:
        #     format_spec = 'en'

        assert format_spec in ['en', 'ch'], ("value must be in 'en, ch' choice!")
        f = (["，", ","], ["’", "'"], ["‘", "'"], ["【", "["], ["】", "]"], ["：", ":"])        # ['ch', 'en']

        if format_spec == 'en':
            for c, e in f:
                self.string = self.string.replace(c, e)
            return self.string

        elif format_spec == 'ch':
            for c, e in f:
                self.string = self.string.replace(e, c)
            return self.string


def is_valid(request, method, *args, **kwargs):
    """
    获取request中的表单数据，验证数据无误返回一个字典，如果有异常数据会返回一个Response对象
    调用格式如：is_valid(request, "POST", "uid", username=None, role=None)
    :param request:
    :param method:
    :param kwargs:
    :return:
    """
    # must = kwargs.pop("must", True)         # 假如must參數沒有被傳遞，那麼這些參數都是必須被傳送的
    keys = list(args) + list(kwargs.keys())
    for key in keys:                                # 设置第一种获取方式（获取Form表单格式数据）
        if method == "GET":
            value = request.GET.get(key, None)
        elif method == "POST":
            value = request.POST.get(key, None)
        elif method == "PUT":
            value = None

        if not value:                               # 设置第二种获取方式（获取转为JSON的数据格式）
            value = request.data.get(key, None)

        if not value:                               # 为空则返回
            if key not in kwargs.keys():
                return Response({"msg": "Parameter '%s' cannot be empty!" % key})
            else:
                value = kwargs[key]
        kwargs[key] = value
    return kwargs


def supplying_list(lis, cont, value=None):
    """
    给lis列表对象补充cont个value，value默认为None
    :param lis: 列表对象
    :param cont: 数值型（补充个数）
    :param value: 补充的参数
    :return: list类型
    """
    for i in range(cont):
        lis.append(value)
    return lis


def list_str_to_int(lis):
    """
    提取列表中的数字型元素，如果是str类型就转换为int类型
    :param lis: 包含list
    :return:
    """
    result = []
    for li in lis:
        try:
            if li.isdigit():             # 检查是否为int类型的字符串
                result.append(int(li))
        except AttributeError:          # 如果不是字符串类型会抛出AttributeError异常
            if type(li) == int:         # 异常时检测是否为int类型
                result.append(li)
    return result


def Response(*args, **kwargs):
    re = response.Response(*args, **kwargs)
    re['Access-Control-Allow-Origin'] = '*'
    # re["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS,DELETE,PUT"
    re["Access-Control-Allow-Credentials"] = "true"
    # re['Content-Type'] = 'application/json'
    return re

def Response_zh(data):
    response = HttpResponse()
    response['Access-Control-Allow-Origin'] = '*'
    response["Access-Control-Allow-Credentials"] = "true"
    response['Content-Type'] = 'application/json'
    response.write(json.dumps(data))
    return response


def randoms(pcs, string=True):
    result = (string and [""] or [0])[0]
    for i in range(pcs):
        result += str(random.randint(0, 9))
    if not result:
        result = int(result)
    return result


class Crypt(object):
    """
    密码的加密模块
    """
    def __init__(self, pwd, coding="utf-8"):
        self.pwd = pwd
        self.coding = coding

    @property
    def make_pwd(self):
        """
        处理明文密码，增加字符操作
        """
        head = random.choice(string.ascii_letters)      # 取随机字母
        end = random.choice(string.digits)              # 取随机数字

        # 在密码的第4位添加随机字母
        self.pwd = self.pwd[:3] + head + self.pwd[3:]

        # 在密码的第6位添加随机数字
        self.pwd = self.pwd[:6] + end + self.pwd[6:]
        return self.pwd

    @property
    def restore_pwd(self):
        """
        还原明文密码的处理，去除增加的字符操作
        """
        self.pwd = self.pwd[:3] + self.pwd[4:6] + self.pwd[7:]
        return self.pwd

    def _encode(self, string):
        return string.encode(self.coding)

    def _decode(self, byte):
        return byte.decode(self.coding)

    def jiami(self):
        """
        Input: "123456"
        Output: "MTIzcjQ1MzY="
        """
        self.pwd = self._encode(self.make_pwd)
        self.pwd = self._decode(base64.b64encode(self.pwd))
        return self.pwd

    def jiemi(self):
        """
        Input: "MTIzcjQ1MzY="
        Output: "123456"
        """
        self.pwd = self._decode(base64.b64decode(self._encode(self.pwd)))
        return self.restore_pwd

    def base64_jiami(self):
        return self._decode(base64.b64encode(self._encode(self.pwd)))

    def base64_jiemi(self):
        return self._decode(base64.b64decode(self._encode(self.pwd)))


def handle_xcsrftoken(string):
    """
    解析客户端传输的头文件参数
    :param string: TOKEN=AHWIEGOHOWAGAWIEGHOAWIHEGOAWI;PID=13545154651
    :return: {"TOKEN": "AHWIEGOHOWAGAWIEGHOAWIHEGOAWI", "PID": "13545154651"}
    """
    result = {}
    for i in string.split(";"):
        j = i.split("=")
        result[j[0]] = j[1]
    return result


@property
def getLocalIP():
    return socket.gethostbyname(socket.getfqdn(socket.gethostname()))


def AuthKey():
    """
    把UTC时间的日期和一个AC自定义Key值组合后，再使用SHA512进行加密处理，并返回大写字串
    :return:
    """
    utcDate = datetime.datetime.utcnow().strftime("%Y-%m-%d")

    # key = '2017-10-09' + 'ajan@6$)c)*8fplq(&!^d6&*l@r)5o0zm%*-ak62hraklqx4e$'
    key = utcDate + settings.WEP_KEY
    # print(key)
    m = hashlib.sha512()
    m.update(key.encode("utf-8"))
    s = m.hexdigest().upper()
    # print(s)
    return s


class DateProcess(object):
    def __init__(self, start, end, typ):
        self.start = self.strp(start)
        self.end = self.strp(end)
        self.typ = typ

    def strp(self, date):
        """
        格式化时间字符串为时间类型
        """
        return datetime.datetime.strptime(date, settings.REST_FRAMEWORK["DATE_FORMAT"])

    def strf(self, date):
        """
        格式化时间类型为时间字符串类型
        """
        return date.strftime(settings.REST_FRAMEWORK["DATE_FORMAT"])

    def action(self):
        return getattr(self, self.typ, lambda: "nothing")

    def get_type(self):
        return ['year', 'month', 'week', 'day']

    def timedelta(self, date, lower=True):
        """
        默認參數date減一天；lower=False時，時間加一天
        :param date:
        :param lower:
        :return:
        """
        if self.typ == "month":
            date = datetime.datetime(year=date.year, month=date.month, day=1)

        if lower:
            return date - datetime.timedelta(days=1)
        else:
            return date + datetime.timedelta(days=1)

    def sort_date(self, dates):
        """
        給當前類返回的時間結果進行排序
        :param dates: {
'2017-3': [datetime.datetime(2017, 3, 1, 0, 0), datetime.datetime(2017, 3, 28, 0, 0)]
'2017-2': [datetime.datetime(2017, 2, 1, 0, 0), datetime.datetime(2017, 2, 31, 0, 0)]}
        :return: [
(2017-2, [datetime.datetime(2017, 2, 1, 0, 0), datetime.datetime(2017, 2, 28, 0, 0)]),
(2017-3, [datetime.datetime(2017, 3, 1, 0, 0), datetime.datetime(2017, 3, 31, 0, 0)])]
        """
        dates = zip(dates.keys(), dates.values())
        return sorted(dates, key=lambda x: x[1][0])

    def year_bk(self):
        result = {}
        DIF = self.end.year - self.start.year

        if DIF == 0:  # 前后为同一年的情况
            result[self.start.year] = [self.start, self.end]
        elif DIF == 1:  # 前后相差一年的情况
            result[self.start.year] = [self.start, self.strp(str(self.start.year) + '-12-31')]
            result[self.start.year + 1] = [self.strp(str(self.end.year) + '-01-01'), self.end]
        else:  # 前后相差多年的情况
            cont = 0
            while DIF > 0:
                if cont == 0:
                    result[self.start.year] = [self.start, self.strp(str(self.start.year) + '-12-31')]
                else:
                    s = self.strp('%s-01-01' % str(self.start.year + cont))
                    e = self.strp('%s-12-31' % str(self.start.year + cont))
                    result[self.start.year + cont] = [s, e]
                cont += 1
                DIF -= 1

            try:
                result[self.end.year] = [self.strp('%s-01-01' % str(self.end.year)), self.end]
            except KeyError:
                pass

        return result

    def year(self):
        result = {}
        DIF = self.end.year - self.start.year
        cont = 0
        while DIF >= 0:
            if cont == 0:  # 处理第一年
                result[self.start.year] = [self.start, self.strp(str(self.start.year) + '-12-31')]
            else:
                s = self.strp('%s-01-01' % str(self.start.year + cont))
                e = self.strp('%s-12-31' % str(self.start.year + cont))
                result[self.start.year + cont] = [s, e]
            cont += 1
            DIF -= 1

        try:
            result[self.end.year][1] = self.end  # 处理最后一年
        except KeyError:
            pass

        return result

    def month(self):
        last = self.end
        result = {}
        cont = 0
        while last > self.start and last.month != self.start.month:
            first = self.timedelta(last)
            result[str(last.year) + "-" + str(last.month)] = [
                datetime.datetime(year=last.year, month=last.month, day=1), last]
            last = first
            cont += 1

        if cont:
            _, last_day_num = calendar.monthrange(self.start.year, self.start.month)
            result[str(self.start.year) + "-" + str(self.start.month)] = [self.start,
                                                                          datetime.datetime(year=self.start.year,
                                                                                            month=self.start.month,
                                                                                            day=last_day_num)]
        else:
            result[str(self.start.year) + "-" + str(self.start.month)] = [self.start, self.end]
        return result

    def month_later(self):
        first = self.start
        start_list = (self.start.year, self.start.month)
        end_list = (self.end.year, self.end.month)
        result = {}
        cont = 0
        while start_list != end_list:
            # _, last_day_num = calendar.monthrange(first.year, first.month)
            last = datetime.datetime(year=start_list[0], month=start_list[1] + 1, day=1)
            result["{0}-{1}".format(start_list[0], start_list[1])] = [first, last]

            first = last
            start_list = (first.year, first.month)
            cont += 1

        # if not cont:        # 假如循环没有被执行，那么直接返回起始的时间
        #     result[self.start.strftime("%Y-%m")] = [self.start, self.end]        # 单数月份会带0的方法
        # else:               # 假如循环被执行，那么最后一个时间修改为最终时间
        #     result[self.end.strftime("%Y-%m")] = [first, self.end]

        if not cont:        # 假如循环没有被执行，那么直接返回起始的时间
            result[str(self.start.year) + "-" + str(self.start.month)] = [self.start, self.end]     # 单数月份不带0
        else:               # 假如循环被执行，那么最后一个时间修改为最终时间
            result[str(self.end.year) + "-" + str(self.end.month)] = [first, self.end]

        return result

    def week(self):
        result = {}
        week = self.start.strftime("%Y-%W")
        result[week] = [self.start]
        while self.start < self.end:
            back = self.timedelta(self.start, lower=False)
            back_week = back.strftime("%Y-%W")
            if back_week != week:
                result[week].append(self.timedelta(back))
                result[back_week] = [back]
            week = back.strftime("%Y-%W")
            self.start = back

        result[self.end.strftime("%Y-%W")].append(self.end)
        return result

    def day(self):
        result = {}
        day = self.strf(self.start)
        result[day] = [self.start]

        while self.start < self.end:
            back = self.timedelta(self.start, lower=False)
            back_day = back.strftime("%Y-%m-%d")
            if back_day != day:
                result[day].append(back)
                result[back_day] = [back]
            day = back.strftime("%Y-%m-%d")
            self.start = back

        result[self.end.strftime("%Y-%m-%d")].append(self.timedelta(self.end, lower=False))
        return result

